package cn.mjnxin.iot.gate.util;

import java.util.Collection;
import java.util.Iterator;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.mjnxin.iot.base.constant.ConstantValue;
import cn.mjnxin.iot.base.log.LogWorker;
import cn.mjnxin.iot.base.util.CommonUtil;
import cn.mjnxin.iot.gate.cache.GateRuntimeCache;
import cn.mjnxin.iot.gate.cache.GateRuntimeCache.HostChannel;
import cn.mjnxin.iot.transfer.TransferExchange;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;

/**
 * 网关工具类
 * @author CLG 2023年10月10日
 * @version V1.0.0
 */
public class GateUtil {
    private static final Logger LOG = LoggerFactory.getLogger(GateUtil.class);
    public static void bannel(){
        LogWorker.logForce("*********************************************************************************************");
        LogWorker.logForce("*********************************************************************************************");
        LogWorker.logForce("--------------------------------------启动网关--------------------------------------------");
        LogWorker.logForce("*********************************************************************************************");
        LogWorker.logForce("*********************************************************************************************");
    }

    public static void terminalUnlink(Integer pid, Integer logLevel, String terminalAddress, Integer gateNum) {
        Collection<HostChannel> hosts = GateRuntimeCache.getHostListByPid4NotifyUnlink(pid, terminalAddress);
        if (hosts == null || hosts.isEmpty()) {
            LogWorker.logForce(String.format("%d|通知Host Terminal[%s] 断网断连时，没有任何处理前置", pid, terminalAddress));
            return;
        }

        ByteBuf buf = null;
        try {
            buf = TransferExchange.terminalLinkChange(ConstantValue.TYPE_TERMINAL_UNLINK, gateNum, terminalAddress, pid, logLevel);
            for (Iterator<HostChannel> itr = hosts.iterator(); itr.hasNext();) {
                HostChannel hostChannel = itr.next();
                LogWorker.logForce(String.format("%d|通知Host[%s] Terminal[%s]断网断连", pid, hostChannel.getHostKey(), terminalAddress));
                hostChannel.getChannel().writeAndFlush(buf.copy());
            }
        } catch (Exception e) {
            LogWorker.error("Terminal Unlink: " + e.getMessage(), e);
            LOG.error(e.getMessage(), e);
        }
        finally {
            if (buf != null) {
                CommonUtil.releaseByteBuf(buf);
            }
        }
    }

    public static void terminalClosed(Integer pid, Integer logLevel, String terminalAddress, Integer gateNum) {
        Collection<HostChannel> hosts = GateRuntimeCache.getHostListByPid4NotifyUnlink(pid, terminalAddress);
        if (hosts == null || hosts.isEmpty()) {
            LogWorker.logForce(String.format("%d|通知Host Terminal[%s] 被断网断连时，没有任何处理前置", pid, terminalAddress));
            return;
        }

        ByteBuf buf = null;
        try {
            buf = TransferExchange.terminalLinkChange(ConstantValue.TYPE_TERMINAL_CLOSED, gateNum, terminalAddress, pid, logLevel);
            for (Iterator<HostChannel> itr = hosts.iterator(); itr.hasNext();) {
                HostChannel hostChannel = itr.next();
                LogWorker.logForce(String.format("%d|通知Host[%s] Terminal[%s]被断网断连", pid, hostChannel.getHostKey(), terminalAddress));
                hostChannel.getChannel().writeAndFlush(buf.copy());
            }
        } catch (Exception e) {
            LogWorker.error("Terminal Closed: " + e.getMessage(), e);
            LOG.error(e.getMessage(), e);
        }
        finally {
            if (buf != null) {
                CommonUtil.releaseByteBuf(buf);
            }
        }
    }

    public static void terminalOut(Integer pid, Integer logLevel, String terminalAddress, Integer gateNum) {
        Collection<HostChannel> hosts = GateRuntimeCache.getHostListByPid4NotifyUnlink(pid, terminalAddress);
        if (hosts == null || hosts.isEmpty()) {
            LogWorker.logForce(String.format("%d|通知Host Terminal[%s] 超时断连时，没有任何处理前置", pid, terminalAddress));
            return;
        }

        ByteBuf buf = null;
        try {
            buf = TransferExchange.terminalLinkChange(ConstantValue.TYPE_TERMINAL_TIMEOUT, gateNum, terminalAddress, pid, logLevel);
            for (Iterator<HostChannel> itr = hosts.iterator(); itr.hasNext();) {
                HostChannel hostChannel = itr.next();
                LogWorker.logForce(String.format("%d|通知Host[%s] Terminal[%s]超时断连", pid, hostChannel.getHostKey(), terminalAddress));
                hostChannel.getChannel().writeAndFlush(buf.copy());
            }
        } catch (Exception e) {
            LogWorker.error("Terminal Timeout: " + e.getMessage(), e);
            LOG.error(e.getMessage(), e);
        }
        finally {
            if (buf != null) {
                CommonUtil.releaseByteBuf(buf);
            }
        }
    }
    
    public static void terminalLink(Integer pid, Integer logLevel, String terminalAddress, Integer gateNum) {
        Collection<HostChannel> hosts = GateRuntimeCache.getHostListByPid4NotifyLink(pid, terminalAddress);
        if (hosts == null || hosts.isEmpty()) {
            LogWorker.logForce(String.format("%d|通知Host Terminal[%s]连接时，没有任何处理前置", pid, terminalAddress));
            return;
        }

        ByteBuf buf = null;
        try {
            buf = TransferExchange.terminalLinkChange(ConstantValue.TYPE_TERMINAL_LINK, gateNum, terminalAddress, pid, logLevel);
            for (Iterator<HostChannel> itr = hosts.iterator(); itr.hasNext();) {
                HostChannel hostChannel = itr.next();
                LogWorker.logForce(String.format("%d|通知Host[%s] Terminal[%s]连接", pid, hostChannel.getHostKey(), terminalAddress));
                hostChannel.getChannel().writeAndFlush(buf.copy());
            }
        } catch (Exception e) {
            LogWorker.error("Terminal Link: " + e.getMessage(), e);
            LOG.error(e.getMessage(), e);
        }
        finally {
            if (buf != null) {
                CommonUtil.releaseByteBuf(buf);
            }
        }
    }

    public static void allTerminalLink(Integer pid, Integer logLevel, Integer gateNum, Channel host) {
        Collection<String> terminalList = GateRuntimeCache.getTerminalListByPid(pid);
        if (terminalList == null || terminalList.isEmpty()) {
            LogWorker.logForce("没有发现任何Terminal，不需通知Host");
            return;
        }

        try {
            for (Iterator<String> itr = terminalList.iterator(); itr.hasNext();) {
                String terminalAddress = itr.next();
                ByteBuf buf = TransferExchange.terminalLinkChange(ConstantValue.TYPE_TERMINAL_LINK, gateNum, terminalAddress, pid, logLevel);
                LogWorker.logForce(String.format("%d|通知Host Terminal[%s]连接", pid, terminalAddress));
                host.writeAndFlush(buf);
            }
        } catch (Exception e) {
            LogWorker.error("allTerminalLink: " + e.getMessage(), e);
            LOG.error(e.getMessage(), e);
        }
    }
    
}
